package com.hhkj.study.admin.course.service.extend.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import com.hhkj.study.admin.course.entity.*;
import com.hhkj.study.admin.course.enums.CourseAssocResourceTypeEnum;
import com.hhkj.study.admin.course.model.podo.CourseDo;
import com.hhkj.study.admin.course.model.podo.CoursePo;
import com.hhkj.study.admin.course.model.res.UserCourseRes;
import com.hhkj.study.admin.course.service.base.CourseService;
import com.hhkj.study.admin.course.service.extend.CourseExtendService;
import com.hhkj.study.admin.goods.model.res.GoodsSkuAssocGoodRes;
import com.hhkj.study.admin.goods.service.extend.GoodsSkuExtendService;
import com.hhkj.study.admin.order.entity.OrderItem;
import com.hhkj.study.admin.order.enums.OrderStatusEnum;
import com.hhkj.study.admin.order.model.podo.OrderItemDo;
import com.hhkj.study.admin.order.model.podo.OrderItemPo;
import com.hhkj.study.admin.order.service.base.OrderItemService;
import com.hhkj.study.admin.resource.service.base.ResourceCourseVideoService;
import com.hhkj.study.admin.teacher.entity.Teacher;
import com.hhkj.study.admin.teacher.service.base.TeacherService;
import com.hhkj.study.admin.teacher.service.extend.TeacherExtendService;
import com.hhkj.study.admin.user.service.biz.UserCourseBizService;
import com.hhkj.study.api.user.model.res.ApiUserListenCourseRes;
import com.ruoyi.common.base.biz.service.extend.BaseExtendServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
*
* @author SERVER
* @since 2024-09-18
*/
@Slf4j
@Service
public class CourseExtendServiceImpl extends BaseExtendServiceImpl<Course, CourseDo, CoursePo, CourseService> implements CourseExtendService {

    @Resource
    private OrderItemService orderItemService;

    @Resource
    private GoodsSkuExtendService goodsSkuExtendService;

    @Resource
    private UserCourseBizService userCourseBizService;

    @Resource
    private TeacherExtendService teacherExtendService;

    @Resource
    private TeacherService teacherService;

    @Resource
    private ResourceCourseVideoService courseVideoService;

    /** 课程表需要过滤的列 */
    private static final List<String> FILTER_COLUMNS = Lists.newArrayList("structure_json");


    @Override
    public List<UserCourseRes> getCourseListByUserId(Long userId, Long courseType) {
        // 查询成功支付的订单
        OrderItemDo orderItemDo = new OrderItemDo();
        orderItemDo.setBuyerId(userId);
        orderItemDo.setStatus(OrderStatusEnum.PAID.getCode());
        List<OrderItemPo> orderItemList = orderItemService.listPoByDo(orderItemDo);
        if (CollectionUtil.isEmpty(orderItemList)) {
            return Lists.newArrayList();
        }
        // 流操作中分别获得订单下的商品id和商品skuId
        Pair<Set<Long>, Set<Long>> orderGoodsPair = orderItemList.stream().collect(Collectors.collectingAndThen(
                Collectors.toList(),
                list -> {
                    Set<Long> orderGoodsIdSet = list.stream().map(OrderItemPo::getGoodsId).collect(Collectors.toCollection(TreeSet::new));
                    Set<Long> orderGoodsSkuIdSet = list.stream().map(OrderItemPo::getGoodsSkuId).collect(Collectors.toCollection(TreeSet::new));
                    return Pair.of(orderGoodsIdSet, orderGoodsSkuIdSet);
                }
        ));

        // 商品sku通过商品id列表设置商品到sku中额外信息 商品有效时间等
        List<GoodsSkuAssocGoodRes> skuAssocGoodList = goodsSkuExtendService.supplyGoodsSkuGoodsByGoodsIdList(orderGoodsPair.getRight(), orderGoodsPair.getLeft(), courseType);
        if (CollectionUtil.isEmpty(skuAssocGoodList)) {
            return Lists.newArrayList();
        }
        Set<Long> showGoodsIdSet = skuAssocGoodList.stream().map(GoodsSkuAssocGoodRes::getGoodsId).collect(Collectors.toSet());
        // orderItem中存储结构是list结合,通过steam方式打散获得商品sku与课程id的map
        Map<Long, Set<Long>> orderCourseIdSetMap = orderItemList.stream().collect(Collectors.groupingBy(
                        OrderItem::getGoodsSkuId,
                        Collectors.mapping(
                                OrderItem::getCourseIdList,
                                Collectors.toSet())))
                .entrySet()
                .stream()
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        entry -> entry.getValue().stream()
                                .flatMap(Collection::stream)
                                .collect(Collectors.toSet())));

        // 订单中跟所有的课程id
        LinkedHashSet<Long> courseIdSet = orderItemList.stream()
                .filter(item -> showGoodsIdSet.contains(item.getGoodsId()) && CollectionUtil.isNotEmpty(item.getCourseIdList()))
                .flatMap(item -> item.getCourseIdList().stream()).collect(Collectors.toCollection(LinkedHashSet::new));
        if (CollectionUtil.isEmpty(courseIdSet)) {
            return Lists.newArrayList();
        }

        // 通过课程列表查询课程详情过滤掉json格式的列,避免数据返回太多
        List<Course> courseList = this.listByIdList(courseIdSet);
        // 按照下单的顺序排序
        List<UserCourseRes> userCourseResOrderList = Lists.newArrayList();
        List<UserCourseRes> userCourseResList = BeanUtil.copyToList(courseList, UserCourseRes.class);
        if (CollectionUtil.isEmpty(userCourseResList)) {
            return Lists.newArrayList();
        }
        courseIdSet.forEach(courseId -> {
            UserCourseRes userCourseRes = userCourseResList.stream().filter(item -> item.getId().equals(courseId)).findFirst().orElse(null);
            if (ObjectUtil.isNotNull(courseId) && ObjectUtil.isNotNull(userCourseRes)) {
                userCourseResOrderList.add(userCourseRes);
            }
        });
        // 组装用户课程其他信息 老师列表 课程学习进度 课程有效期等
        assignUserCourseResList(userCourseResOrderList, skuAssocGoodList, orderCourseIdSetMap, orderItemList, userId);
        return userCourseResOrderList;
    }


    @Override
    public boolean saveStatCourseAssocResource(Course course, List<CourseStructure> structureJsonList) {
        List<CourseStructure> structureJson = course.getStructureJson();
        if (CollectionUtil.isEmpty(structureJson)) {
            return false;
        }
        List<CourseStructure> courseResourceFinalList = Lists.newArrayList();
        structureJson.forEach(courseStructure -> {
            List<CourseStructure> lastChildrenList = getLastChildrenList(courseStructure);
            if (CollectionUtil.isNotEmpty(lastChildrenList)) {
                courseResourceFinalList.addAll(lastChildrenList);
            }
        });

        Long courseId = course.getId();
        // 课程资源处理
        Pair<List<CourseAssocResourceStat>, List<CourseResourceRelevance>> courseResourcePair = doCourseAssocResource(courseResourceFinalList, courseId);

        course = new Course();
        course.setId(courseId);
        if (CollectionUtil.isNotEmpty(structureJsonList)) {
            course.setStructureJson(structureJsonList);
        }
        CourseResourceInfo courseResourceInfo = new CourseResourceInfo(courseResourcePair.getLeft(), courseResourcePair.getRight());
        course.setAssocResourceStat(courseResourceInfo);
        return this.getService().updateById(course);
    }

    @Override
    public List<Course> listByIdList(Collection<? extends Serializable> idList) {
        if (CollectionUtil.isEmpty(idList)) {
            return Lists.newArrayList();
        }
        LambdaQueryWrapper<Course> courseQuery = new LambdaQueryWrapper<>();
        courseQuery.select(Course.class, c -> !FILTER_COLUMNS.contains(c.getColumn()));
        courseQuery.in(Course::getId, idList);
        return this.getService().list(courseQuery);
    }

    @Override
    public List<Course> getCourseResList(List<Long> courseIdList, List<Course> courseList) {
        if (CollectionUtil.isEmpty(courseIdList) || CollectionUtil.isEmpty(courseList)) {
            return Lists.newArrayList();
        }
        return courseList.stream().filter(course -> courseIdList.contains(course.getId())).collect(Collectors.toList());
    }

    @Override
    public CourseAssocResourceStat getCourseAssocResourceStat(Long courseId, CourseAssocResourceTypeEnum resourceTypeEnum) {
        LambdaQueryWrapper<Course> courseQuery = new LambdaQueryWrapper<>();
        courseQuery.select(Course.class, c -> !FILTER_COLUMNS.contains(c.getColumn()));
        courseQuery.eq(Course::getId, courseId).last("LIMIT 1");
        Course course = this.getService().getOne(courseQuery);
        if (ObjectUtil.isNull(course)) {
            return null;
        }
        Optional<CourseAssocResourceStat> courseAssocResourceStat = Optional.ofNullable(course.getAssocResourceStat()).map(CourseResourceInfo::getCourseAssocResourceList).orElse(Lists.newArrayList()).stream().filter(e -> resourceTypeEnum.getCode().equals(e.getResourceType())).findFirst();
        return courseAssocResourceStat.orElse(null);
    }


    /**
     * 处理课程表内的资源统计
     *
     * @param courseResourceFinalList
     * @param courseId
     * @return
     */
    private Pair<List<CourseAssocResourceStat>, List<CourseResourceRelevance>> doCourseAssocResource(List<CourseStructure> courseResourceFinalList, Long courseId) {
        // 课程表中视频 讲义 题库统计
        Map<String, List<CourseStructure>> resourceTypeMap = courseResourceFinalList.stream().collect(Collectors.groupingBy(CourseStructure::getType));
        List<CourseAssocResourceStat> courseAssocResourceList = Lists.newArrayList();
        resourceTypeMap.forEach((resourceType, resourceList) -> {
            List<Long> resourceIdList = resourceList.stream().map(CourseStructure::getTypeAssoId).collect(Collectors.toList());
            Long videoTotalDuration = 0L;
            if (CourseAssocResourceTypeEnum.VIDEO.getCode().equals(resourceType)) {
                // 视频总时长
                videoTotalDuration = courseVideoService.calculateLessonTimeByIdList(resourceIdList);
            }

            courseAssocResourceList.add(
                    new CourseAssocResourceStat().setCourseId(courseId).setResourceCount(resourceList.size())
                    .setResourceType(resourceType)
                    .setResourceIdList(resourceIdList).setVideoTotalDuration(videoTotalDuration));
        });

        // 课程下视频关联的讲义 题库
        /*List<CourseResourceRelevance> courseResourceRelevanceList = courseResourceFinalList.stream().map(courseStructure -> {
            CourseResourceRelevance courseResourceRelevance = new CourseResourceRelevance();
            if (CourseAssocResourceTypeEnum.QUESTION.getCode().equals(courseStructure.getType())) {
                courseResourceRelevance.setQuestionBankId(courseStructure.getTypeAssoId());
            } else {
                courseResourceRelevance.setQuestionBankId(courseStructure.getQuestionId());
            }
            courseResourceRelevance.setResourceId(courseStructure.getTypeAssoId());
            courseResourceRelevance.setResourceType(courseStructure.getType());
            courseResourceRelevance.setCourseId(courseId);
            courseResourceRelevance.setDocId(courseStructure.getDocId());
            return courseResourceRelevance;
        }).collect(Collectors.toList());*/

        return Pair.of(courseAssocResourceList, Lists.newArrayList());
    }


    /**
     * 处理课程中订单id
     * @param userCourseResList
     * @param orderItemList
     */
    private void processUserCourseBase(List<UserCourseRes> userCourseResList, List<OrderItemPo> orderItemList) {
        List<Long> teacherAllIdList = userCourseResList.stream()
                .filter(item -> ObjectUtil.isNotNull(item) && CollectionUtil.isNotEmpty(item.getTeacherIdList()))
                .flatMap(item -> item.getTeacherIdList().stream()).collect(Collectors.toList());
        List<Teacher> teacherList;
        if (CollectionUtil.isNotEmpty(teacherAllIdList)) {
            teacherList = teacherService.listByIds(teacherAllIdList);
        } else {
            teacherList = Lists.newArrayList();
        }
        userCourseResList.forEach(userCourse -> {
            orderItemList.stream().filter(orderItem -> ObjectUtil.isNotNull(orderItem) && CollectionUtil.isNotEmpty(orderItem.getCourseIdList()) && orderItem.getCourseIdList().contains(userCourse.getId())).findFirst().ifPresent(orderItem -> {
                userCourse.setOrderItemId(orderItem.getId());
                if (CollectionUtil.isNotEmpty(teacherList)) {
                    List<Teacher> teacherCourseList = teacherExtendService.getTeacherList(userCourse.getTeacherIdList(), teacherList);
                    userCourse.setTeacherList(teacherCourseList);
                }
            });
        });

    }

    /**
     * 通过订单和商品sku设置到用户课程信息
     *
     * @param userCourseResList
     * @param skuAssocGoodList
     * @param orderCourseIdSetMap
     * @param orderItemList       订单列表主要处理订单内的课程学习情况
     * @param userId
     */
    private void assignUserCourseResList(List<UserCourseRes> userCourseResList, List<GoodsSkuAssocGoodRes> skuAssocGoodList, Map<Long, Set<Long>> orderCourseIdSetMap, List<OrderItemPo> orderItemList, Long userId){
        // 用户课程设置子订单 老师等基本信息
        processUserCourseBase(userCourseResList, orderItemList);
        // 用户课程学习情况统计 map集合
        List<ApiUserListenCourseRes> orderUserCourseStudyResList = userCourseBizService.handlerOrderCourseList(orderItemList, userId);
        Map<Long, ApiUserListenCourseRes> userOrderCourseStudyResMap = orderUserCourseStudyResList.stream().collect(Collectors.toMap(ApiUserListenCourseRes::getCourseId, Function.identity(), (o, d) -> {
            d.setCount(d.getCount() + o.getCount());
            return d;
        }));
        userCourseResList.forEach(userCourseRes -> orderCourseIdSetMap.entrySet().stream()
                .filter(entry -> entry.getValue().contains(userCourseRes.getId())).findFirst()
                .flatMap(entry -> skuAssocGoodList.stream().filter(sku -> sku.getId().equals(entry.getKey())).findFirst())
                .ifPresent(sku -> {
                    userCourseRes.setValidStartTime(sku.getValidStartTime());
                    userCourseRes.setValidEndTime(sku.getValidEndTime());
                    userCourseRes.setCategoryParentName(sku.getCategoryParentName());
                    userCourseRes.setGoodsSkuName(sku.getName());
                    userCourseRes.setGoodsName(sku.getGoodsName());
                    if (StrUtil.isNotBlank(userCourseRes.getGoodsName())) {
                        userCourseRes.setName(StrUtil.format("{}-{}", userCourseRes.getGoodsName(), userCourseRes.getName()));
                    }

                    // 课程关联资源的统计信息 包括视频数 直播数等
                    CourseResourceInfo assocResourceInfo = userCourseRes.getAssocResourceStat();
                    if (ObjectUtil.isNotNull(assocResourceInfo) && CollectionUtil.isNotEmpty(assocResourceInfo.getCourseAssocResourceList())) {
                        List<CourseAssocResourceStat> assocResourceStatList = assocResourceInfo.getCourseAssocResourceList();
                        // 课程资源下视频总课时
                        assocResourceStatList.stream().filter(e -> CourseAssocResourceTypeEnum.VIDEO.getCode().equals(e.getResourceType())).findFirst().ifPresent(resourceStat ->{
                            userCourseRes.setLessonCount(resourceStat.getResourceCount());
                        });
                    }

                    ApiUserListenCourseRes userOrderListenCourseRes = userOrderCourseStudyResMap.get(userCourseRes.getId());
                    userCourseRes.setFinishLessonCount(0);
                    // 统计数据不为空而且用户学习数据与订单和课程匹配则赋值
                    if (ObjectUtil.isNotNull(userOrderListenCourseRes) && StrUtil.equals(userOrderListenCourseRes.getOrderItemConcatCourseId(), userCourseRes.getOrderItemConcatCourseId())) {
                        userCourseRes.setFinishLessonCount(userOrderListenCourseRes.getCount());
                        if (ObjectUtil.isNotEmpty(userCourseRes.getLessonCount())
                                && userCourseRes.getFinishLessonCount() > userCourseRes.getLessonCount()) {
                            userCourseRes.setFinishLessonCount(userCourseRes.getLessonCount());
                        }
                    }

                }
        ));
    }

    /**
     * 递归课程下资源
     * @param courseStructure
     * @return
     */
    private List<CourseStructure> getLastChildrenList(CourseStructure courseStructure){
        List<CourseStructure> leafChildren = Lists.newArrayList();
        if (CollectionUtil.isEmpty(courseStructure.getChildren())) {
            return leafChildren;
        }
        for (CourseStructure child : courseStructure.getChildren()) {
            if (CollectionUtil.isEmpty(child.getChildren())) {
                leafChildren.add(child);
            } else {
                leafChildren.addAll(getLastChildrenList(child));
            }
        }
        return leafChildren;
    }
}
